Reactã®useImperativeHandleããã¯ã掻çšããŠãrefãã«ã¹ã¿ãã€ãºããç¹å®ã®ã³ã³ããŒãã³ãæ©èœãå ¬éããŸããã·ãŒã ã¬ã¹ãªçµ±åãšå¶åŸ¡ã®ããã®é«åºŠãªãã¿ãŒã³ãšãã¹ããã©ã¯ãã£ã¹ãåŠã³ãŸãã
React useImperativeHandle: Refã«ã¹ã¿ãã€ãºãã¿ãŒã³ããã¹ã¿ãŒãã
Reactã®useImperativeHandleããã¯ã¯ãReact.forwardRefã䜿çšããéã«èŠªã³ã³ããŒãã³ãã«å
¬éãããã€ã³ã¹ã¿ã³ã¹å€ãã«ã¹ã¿ãã€ãºããããã®åŒ·åãªããŒã«ã§ããReactã¯äžè¬çã«å®£èšåããã°ã©ãã³ã°ãæšå¥šããŠããŸãããuseImperativeHandleã¯ãå¿
èŠãªå Žåã«åœä»€çãªçžäºäœçšã®ããã®å¶åŸ¡ããããšã¹ã±ãŒãããããæäŸããŸãããã®èšäºã§ã¯ãReactã³ã³ããŒãã³ãã匷åããããã«useImperativeHandleã广çã«æŽ»çšããããã®ããŸããŸãªãŠãŒã¹ã±ãŒã¹ããã¹ããã©ã¯ãã£ã¹ãããã³é«åºŠãªãã¿ãŒã³ã«ã€ããŠèª¬æããŸãã
RefsãšforwardRefãçè§£ãã
useImperativeHandleã«å
¥ãåã«ãrefsãšforwardRefãçè§£ããããšãäžå¯æ¬ ã§ããRefsã¯ãåºã«ãªãDOMããŒããŸãã¯Reactã³ã³ããŒãã³ãã€ã³ã¹ã¿ã³ã¹ã«ã¢ã¯ã»ã¹ããæ¹æ³ãæäŸããŸãããã ããçŽæ¥ã¢ã¯ã»ã¹ã¯Reactã®äžæ¹åããŒã¿ãããŒã®ååã«éåããå¯èœæ§ããããæ§ããã«äœ¿çšããå¿
èŠããããŸãã
forwardRefã䜿çšãããšãrefãåã³ã³ããŒãã³ãã«æž¡ãããšãã§ããŸããããã¯ã芪ã³ã³ããŒãã³ããåå
ã®DOMèŠçŽ ãŸãã¯ã³ã³ããŒãã³ããšçŽæ¥ããåãããå¿
èŠãããå Žåã«éèŠã§ããåºæ¬çãªäŸã次ã«ç€ºããŸãã
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const MyInput = forwardRef((props, ref) => {
return <input ref={ref} {...props} />; // Assign the ref to the input element
});
const ParentComponent = () => {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus(); // Imperatively focus the input
};
return (
<div>
<MyInput ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
export default ParentComponent;
useImperativeHandleã®ç޹ä»
useImperativeHandleã䜿çšãããšãforwardRefã«ãã£ãŠå
¬éãããã€ã³ã¹ã¿ã³ã¹å€ãã«ã¹ã¿ãã€ãºã§ããŸããDOMããŒããŸãã¯ã³ã³ããŒãã³ãã€ã³ã¹ã¿ã³ã¹å
šäœãå
¬éãã代ããã«ãç¹å®ã®ã¡ãœãããŸãã¯ããããã£ãéžæçã«å
¬éã§ããŸããããã«ããã芪ã³ã³ããŒãã³ããåãšå¯Ÿè©±ããããã®å¶åŸ¡ãããã€ã³ã¿ãŒãã§ã€ã¹ãæäŸãããããçšåºŠã®ã«ãã»ã«åãç¶æãããŸãã
useImperativeHandleããã¯ã¯ã次ã®3ã€ã®åŒæ°ãåãå
¥ããŸãã
- ref:
forwardRefãä»ããŠèŠªã³ã³ããŒãã³ãããæž¡ãããrefãªããžã§ã¯ãã - createHandle: å ¬éããå€ãè¿ã颿°ããã®é¢æ°ã¯ã芪ã³ã³ããŒãã³ããrefãä»ããŠã¢ã¯ã»ã¹ã§ããã¡ãœãããŸãã¯ããããã£ãå®çŸ©ã§ããŸãã
- dependencies: äŸåé¢ä¿ã®ãªãã·ã§ã³ã®é
åããããã®äŸåé¢ä¿ã®ããããã倿Žãããå Žåã«ã®ã¿ã
createHandle颿°ãåå®è¡ãããŸããããã¯ãuseEffectã®äŸåé¢ä¿é åã«äŒŒãŠããŸãã
åºæ¬çãªuseImperativeHandleã®äŸ
useImperativeHandleã䜿çšããŠãåã®äŸã倿ŽããŠfocusã¡ãœãããšblurã¡ãœããã®ã¿ãå
¬éããä»ã®å
¥åèŠçŽ ã®ããããã£ãžã®çŽæ¥ã¢ã¯ã»ã¹ãé²ããŸãã
import React, { useRef, forwardRef, useImperativeHandle } from 'react';
const MyInput = forwardRef((props, ref) => {
const inputRef = useRef(null);
useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
},
blur: () => {
inputRef.current.blur();
},
}), []);
return <input ref={inputRef} {...props} />; // Assign the ref to the input element
});
const ParentComponent = () => {
const inputRef = useRef(null);
const focusInput = () => {
inputRef.current.focus(); // Imperatively focus the input
};
return (
<div>
<MyInput ref={inputRef} />
<button onClick={focusInput}>Focus Input</button>
</div>
);
};
export default ParentComponent;
ãã®äŸã§ã¯ã芪ã³ã³ããŒãã³ãã¯inputRef.currentãªããžã§ã¯ãã§focusã¡ãœãããšblurã¡ãœããã®ã¿ãåŒã³åºãããšãã§ããŸããå
¥åèŠçŽ ã®ä»ã®ããããã£ã«çŽæ¥ã¢ã¯ã»ã¹ããããšã¯ã§ãããã«ãã»ã«åã匷åãããŸãã
äžè¬çãªuseImperativeHandleãã¿ãŒã³
1. ç¹å®ã®ã³ã³ããŒãã³ãã¡ãœããã®å ¬é
äžè¬çãªãŠãŒã¹ã±ãŒã¹ã¯ã芪ã³ã³ããŒãã³ããããªã¬ãŒããå¿ èŠãããåã³ã³ããŒãã³ãããã¡ãœãããå ¬éããããšã§ããããšãã°ãã«ã¹ã¿ã ãããªãã¬ãŒã€ãŒã³ã³ããŒãã³ããæ€èšããŠãã ããã
import React, { useRef, forwardRef, useImperativeHandle, useState } from 'react';
const VideoPlayer = forwardRef((props, ref) => {
const videoRef = useRef(null);
const [isPlaying, setIsPlaying] = useState(false);
const play = () => {
videoRef.current.play();
setIsPlaying(true);
};
const pause = () => {
videoRef.current.pause();
setIsPlaying(false);
};
useImperativeHandle(ref, () => ({
play,
pause,
togglePlay: () => {
if (isPlaying) {
pause();
} else {
play();
}
},
}), [isPlaying]);
return (
<div>
<video ref={videoRef} src={props.src} controls={false} />
<button onClick={() => ref.current.togglePlay()}>Toggle Play</button>
</div>
);
});
const ParentComponent = () => {
const playerRef = useRef(null);
return (
<div>
<VideoPlayer ref={playerRef} src="video.mp4" />
<button onClick={() => playerRef.current.play()}>Play Video</button>
</div>
);
};
export default ParentComponent;
ãã®äŸã§ã¯ã芪ã³ã³ããŒãã³ãã¯playerRef.currentãªããžã§ã¯ãã§playãpauseããŸãã¯togglePlayãåŒã³åºãããšãã§ããŸãããããªãã¬ãŒã€ãŒã³ã³ããŒãã³ãã¯ããããªèŠçŽ ãšãã®åç/äžæåæ¢ããžãã¯ãã«ãã»ã«åããŸãã
2. ã¢ãã¡ãŒã·ã§ã³ãšãã©ã³ãžã·ã§ã³ã®å¶åŸ¡
useImperativeHandleã¯ã芪ã³ã³ããŒãã³ãããåã³ã³ããŒãã³ãå
ã®ã¢ãã¡ãŒã·ã§ã³ãŸãã¯ãã©ã³ãžã·ã§ã³ãããªã¬ãŒããã®ã«åœ¹ç«ã¡ãŸãã
import React, { useRef, forwardRef, useImperativeHandle, useState } from 'react';
const AnimatedBox = forwardRef((props, ref) => {
const boxRef = useRef(null);
const [isAnimating, setIsAnimating] = useState(false);
const animate = () => {
setIsAnimating(true);
// Add animation logic here (e.g., using CSS transitions)
setTimeout(() => {
setIsAnimating(false);
}, 1000); // Duration of the animation
};
useImperativeHandle(ref, () => ({
animate,
}), []);
return (
<div
ref={boxRef}
style={{
width: 100,
height: 100,
backgroundColor: 'blue',
transition: 'transform 1s ease-in-out',
transform: isAnimating ? 'translateX(100px)' : 'translateX(0)',
}}
/>
);
});
const ParentComponent = () => {
const boxRef = useRef(null);
return (
<div>
<AnimatedBox ref={boxRef} />
<button onClick={() => boxRef.current.animate()}>Animate Box</button>
</div>
);
};
export default ParentComponent;
芪ã³ã³ããŒãã³ãã¯ãboxRef.current.animate()ãåŒã³åºãããšã«ãããAnimatedBoxã³ã³ããŒãã³ãã®ã¢ãã¡ãŒã·ã§ã³ãããªã¬ãŒã§ããŸããã¢ãã¡ãŒã·ã§ã³ããžãã¯ã¯ãåã³ã³ããŒãã³ãå
ã«ã«ãã»ã«åãããŠããŸãã
3. ã«ã¹ã¿ã ãã©ãŒã ã®æ€èšŒã®å®è£
useImperativeHandleã¯ã芪ã³ã³ããŒãã³ããåãã©ãŒã ãã£ãŒã«ãå
ã®æ€èšŒããžãã¯ãããªã¬ãŒããå¿
èŠãããè€éãªãã©ãŒã æ€èšŒã·ããªãªã容æã«ããããšãã§ããŸãã
import React, { useRef, forwardRef, useImperativeHandle, useState } from 'react';
const InputField = forwardRef((props, ref) => {
const inputRef = useRef(null);
const [error, setError] = useState('');
const validate = () => {
if (inputRef.current.value === '') {
setError('This field is required.');
return false;
} else {
setError('');
return true;
}
};
useImperativeHandle(ref, () => ({
validate,
}), []);
return (
<div>
<input ref={inputRef} {...props} />
{error && <p style={{ color: 'red' }}>{error}</p>}
</div>
);
});
const ParentForm = () => {
const nameRef = useRef(null);
const emailRef = useRef(null);
const handleSubmit = () => {
const isNameValid = nameRef.current.validate();
const isEmailValid = emailRef.current.validate();
if (isNameValid && isEmailValid) {
alert('Form is valid!');
} else {
alert('Form is invalid.');
}
};
return (
<form>
<InputField ref={nameRef} type="text" placeholder="Name" />
<InputField ref={emailRef} type="email" placeholder="Email" />
<button type="button" onClick={handleSubmit}>Submit</button>
</form>
);
};
export default ParentForm;
芪ãã©ãŒã ã³ã³ããŒãã³ãã¯ãnameRef.current.validate()ãšemailRef.current.validate()ãåŒã³åºãããšã«ãããåInputFieldã³ã³ããŒãã³ãå
ã®æ€èšŒããžãã¯ãããªã¬ãŒã§ããŸããåå
¥åãã£ãŒã«ãã¯ãç¬èªã®æ€èšŒã«ãŒã«ãšãšã©ãŒã¡ãã»ãŒãžãåŠçããŸãã
é«åºŠãªèæ ®äºé ãšãã¹ããã©ã¯ãã£ã¹
1. åœä»€çãªçžäºäœçšã®æå°å
useImperativeHandleã¯åœä»€çãªã¢ã¯ã·ã§ã³ãå®è¡ããæ¹æ³ãæäŸããŸããããã®äœ¿çšéãæå°éã«æããããšãéèŠã§ããåœä»€çãªãã¿ãŒã³ãé床ã«äœ¿çšãããšãã³ãŒãã®çè§£ããã¹ããããã³ä¿å®ãé£ãããªãå¯èœæ§ããããŸãã宣èšçãªã¢ãããŒãïŒããšãã°ãpropsãæž¡ããç¶æ
ã®æŽæ°ã䜿çšããïŒã§åãçµæãåŸããããã©ãããæ€èšããŠãã ããã
2. æ éãªAPIèšèš
useImperativeHandleã䜿çšããå Žåã¯ã芪ã³ã³ããŒãã³ãã«å
¬éããAPIãæ
éã«èšèšããŠãã ãããå¿
èŠãªã¡ãœãããšããããã£ã®ã¿ãå
¬éããå
éšå®è£
ã®è©³çްãå
¬éããªãã§ãã ãããããã«ãããã«ãã»ã«åãä¿é²ãããã³ã³ããŒãã³ãã倿Žã«å¯ŸããŠããå埩åãé«ãŸããŸãã
3. äŸåé¢ä¿ã®ç®¡ç
useImperativeHandleã®äŸåé¢ä¿é
åã«çްå¿ã®æ³šæãæã£ãŠãã ãããäžèŠãªäŸåé¢ä¿ãå«ãããšãcreateHandle颿°ãå¿
èŠä»¥äžã«é »ç¹ã«åå®è¡ããããããããã©ãŒãã³ã¹ã®åé¡ãçºçããå¯èœæ§ããããŸããéã«ãå¿
èŠãªäŸåé¢ä¿ãçç¥ãããšãå€ãå€ãäºæããªãåäœãçºçããå¯èœæ§ããããŸãã
4. ã¢ã¯ã»ã·ããªãã£ã®èæ ®äºé
useImperativeHandleã䜿çšããŠDOMèŠçŽ ãæäœããå Žåã¯ãã¢ã¯ã»ã·ããªãã£ãç¶æããŠããããšã確èªããŠãã ãããããšãã°ãããã°ã©ã ã§èŠçŽ ã«ãã©ãŒã«ã¹ããå Žåã¯ããã©ãŒã«ã¹ã倿Žãããããšãã¹ã¯ãªãŒã³ãªãŒããŒã«éç¥ããããã«ãaria-live屿§ãèšå®ããããšãæ€èšããŠãã ããã
5. åœä»€åã³ã³ããŒãã³ãã®ãã¹ã
useImperativeHandleã䜿çšããã³ã³ããŒãã³ãã®ãã¹ãã¯å°é£ãªå ŽåããããŸããå
¬éãããã¡ãœãããæåŸ
ã©ããã«åäœããããšã確èªããã«ã¯ãã¢ãã¯æè¡ã䜿çšãããããã¹ãã§refã«çŽæ¥ã¢ã¯ã»ã¹ããå¿
èŠãããå ŽåããããŸãã
6. åœéåïŒi18nïŒã®èæ ®äºé
useImperativeHandleã䜿çšããŠããã¹ããæäœããããæ
å ±ã衚瀺ããããããŠãŒã¶ãŒåãã®ã³ã³ããŒãã³ããå®è£
ããå Žåã¯ãåœéåãèæ
®ããŠããããšã確èªããŠãã ãããããšãã°ãæ¥ä»ããã«ãŒãå®è£
ããå Žåã¯ãæ¥ä»ããŠãŒã¶ãŒã®ãã±ãŒã«ã«åŸã£ãŠãã©ãŒããããããŠããããšã確èªããŠãã ãããåæ§ã«ããšã©ãŒã¡ãã»ãŒãžã衚瀺ããå Žåã¯ãi18nã©ã€ãã©ãªã䜿çšããŠããŒã«ã©ã€ãºãããã¡ãã»ãŒãžãæäŸããŸãã
7. ããã©ãŒãã³ã¹ãžã®åœ±é¿
useImperativeHandleèªäœã¯ãæ¬è³ªçã«ããã©ãŒãã³ã¹ã®ããã«ããã¯ãå°å
¥ãããã®ã§ã¯ãããŸããããå
¬éãããã¡ãœãããä»ããŠå®è¡ãããã¢ã¯ã·ã§ã³ã¯ãããã©ãŒãã³ã¹ã«åœ±é¿ãäžããå¯èœæ§ããããŸããããšãã°ãè€éãªã¢ãã¡ãŒã·ã§ã³ãããªã¬ãŒããããã¡ãœããå
ã§ã³ã¹ãã®ãããèšç®ãå®è¡ããããããšãã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ã«åœ±é¿ãäžããå¯èœæ§ããããŸããã³ãŒãããããã¡ã€ãªã³ã°ããããã«å¿ããŠæé©åããŸãã
useImperativeHandleã®ä»£æ¿ææ®µ
å€ãã®å Žåããã宣èšçãªã¢ãããŒããæ¡çšããããšã§ãuseImperativeHandleãå®å
šã«åé¿ã§ããŸããããã€ãã®ä»£æ¿ææ®µã次ã«ç€ºããŸãã
- Propsãšç¶æ : ããŒã¿ãæž¡ããã€ãã³ããã³ãã©ãŒãpropsãšããŠåã³ã³ããŒãã³ãã«æž¡ãã芪ã³ã³ããŒãã³ããç¶æ ã管çã§ããããã«ããŸãã
- Context API: Context APIã䜿çšããŠãpropããªã«ãè¡ããã«ã³ã³ããŒãã³ãéã§ç¶æ ãšã¡ãœãããå ±æããŸãã
- ã«ã¹ã¿ã ã€ãã³ã: åã³ã³ããŒãã³ãããã«ã¹ã¿ã ã€ãã³ãããã£ã¹ããããã芪ã³ã³ããŒãã³ãã§ãããããªãã¹ã³ããŸãã
çµè«
useImperativeHandleã¯ãReactã§refãã«ã¹ã¿ãã€ãºããç¹å®ã®ã³ã³ããŒãã³ãæ©èœãå
¬éããããã®è²ŽéãªããŒã«ã§ãããã®æ©èœãšå¶éãçè§£ããããšã§ãã«ãã»ã«åãšå¶åŸ¡ã®çšåºŠãç¶æããªããã广çã«æŽ»çšããŠã³ã³ããŒãã³ãã匷åã§ããŸããåœä»€çãªçžäºäœçšãæå°éã«æããAPIãæ
éã«èšèšããã¢ã¯ã»ã·ããªãã£ãšããã©ãŒãã³ã¹ãžã®åœ±é¿ãèæ
®ããããšãå¿ããªãã§ãã ãããããä¿å®ãããããã¹ãå¯èœãªã³ãŒããäœæããããã«ãå¯èœãªéã宣èšçãªã¢ãããŒããæ€èšããŠãã ããã
ãã®ã¬ã€ãã§ã¯ãuseImperativeHandleããã®äžè¬çãªãã¿ãŒã³ãããã³é«åºŠãªèæ
®äºé
ã«ã€ããŠå
æ¬çãªæŠèŠã説æããŸããããããã®ååãé©çšããããšã§ããã®åŒ·åãªReactããã¯ã®å¯èœæ§ãæå€§éã«åŒãåºããããå
ç¢ã§æè»ãªãŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ãæ§ç¯ã§ããŸãã